//noinspection JSUnresolvedFunction
/**
 * chessboard.js - Javascript chess library
 *
 * module for require.js
 *
 * http://code.google.com/p/fics-meets-html5/
 *
 * Copyright 2012, 2013 Markus Kupke
 */

define(function () {


    var chesslib = chesslib || {};

	chesslib.board = {}; //namespace for functions around the board
	chesslib.board.boards = [];  //nodes that hold chessboards
	chesslib.board.images = {};
	chesslib.board.images.empty = ""; 
	chesslib.board.images.emptyImageTag = document.createElement("IMG");
//	this empty image is taken from http://commons.wikimedia.org/wiki/File:Tv_blank.svg
	chesslib.board.images.emptyImageTag.setAttribute("src", chesslib.board.images.empty);
	chesslib.board.images.emptyImageTag.style.width = "100%";

	chesslib.board.images.pwSrc = 'mimes/BlackPawnWhiteField.svg'; 
	chesslib.board.images.pbSrc = 'mimes/BlackPawnBlackField.svg'; 
	chesslib.board.images.PwSrc = 'mimes/WhitePawnWhiteField.svg'; 
	chesslib.board.images.PbSrc = 'mimes/WhitePawnBlackField.svg'; 
	chesslib.board.images.rwSrc = 'mimes/BlackRookWhiteField.svg'; 
	chesslib.board.images.rbSrc = 'mimes/BlackRookBlackField.svg'; 
	chesslib.board.images.RwSrc = 'mimes/WhiteRookWhiteField.svg'; 
	chesslib.board.images.RbSrc = 'mimes/WhiteRookBlackField.svg'; 
	chesslib.board.images.nwSrc = 'mimes/BlackKnightWhiteField.svg'; 
	chesslib.board.images.nbSrc = 'mimes/BlackKnightBlackField.svg'; 
	chesslib.board.images.NwSrc = 'mimes/WhiteKnightWhiteField.svg'; 
	chesslib.board.images.NbSrc = 'mimes/WhiteKnightBlackField.svg'; 
	chesslib.board.images.bwSrc = 'mimes/BlackBishopWhiteField.svg'; 
	chesslib.board.images.bbSrc = 'mimes/BlackBishopBlackField.svg'; 
	chesslib.board.images.BwSrc = 'mimes/WhiteBishopWhiteField.svg'; 
	chesslib.board.images.BbSrc = 'mimes/WhiteBishopBlackField.svg'; 
	chesslib.board.images.qwSrc = 'mimes/BlackQueenWhiteField.svg'; 
	chesslib.board.images.qbSrc = 'mimes/BlackQueenBlackField.svg'; 
	chesslib.board.images.QwSrc = 'mimes/WhiteQueenWhiteField.svg'; 
	chesslib.board.images.QbSrc = 'mimes/WhiteQueenBlackField.svg'; 
	chesslib.board.images.kwSrc = 'mimes/BlackKingWhiteField.svg'; 
	chesslib.board.images.kbSrc = 'mimes/BlackKingBlackField.svg'; 
	chesslib.board.images.KwSrc = 'mimes/WhiteKingWhiteField.svg'; 
	chesslib.board.images.KbSrc = 'mimes/WhiteKingBlackField.svg'; 
	chesslib.board.codeSnippets = {};

	chesslib.board.codeSnippets.onClick = function (e) {
		var board_move;
        var field = this.id.split('_');
		field = field[field.length-1];
		var board = this.parentNode.parentNode.chess;
        board_move = board.move;
        if(board_move){ //the user clicked something already
			for (var m in board_move) {
				if (!(board_move.hasOwnProperty(m))) continue;
				var move = m;
			};
			if (board_move.hasOwnProperty(field)) { //the user wants to do take back the started move
				for (var i in board_move[field]) {
					if (!(board_move[field].hasOwnProperty(i))) continue;
					if (!(board.fields.hasOwnProperty(board_move[field][i]))) continue;
					board.fields[board_move[field][i]].removeEventListener('click',chesslib.board.codeSnippets.onClick,false);
					board.fields[board_move[field][i]].classList.remove('chesshighlight');
				};
				this.classList.remove('chesshighlight');
				delete board.move;
			} else { //the user chooses the field to move to or clicked on a different start field
				if (this.classList.contains('chesshighlight')) {  //clicked the field to move to
					var promo = false;
					if((board_move[move].length === 1)&&(board_move[move][0].indexOf('?') === 2)) { //promotion
						promo = true;
					};
					board_move[move] = field;
					var changes = {};
					changes[field] = board.fields[move].chess.figure;
					changes[move] = '-';
					//damn enpassant
					if ((board.fields[move].chess.figure === 'p' || 
							board.fields[move].chess.figure === 'P') && 
							!(board.fields[field].chess.figure)) {
						// we have to clear the pawn from the field in front the "field" field
						if (field[1]==='3') {
							var field_with_superfluous_pawn = field[0] + 4;
						} else{
							var field_with_superfluous_pawn = field[0] + 5;
						}
						if (field_with_superfluous_pawn!==move){
							changes[field_with_superfluous_pawn] = '-';
						} 
					}
					board.setFigures(changes);
					for (var f in board.fields){
						if(!(board.fields.hasOwnProperty(f))) continue;
						board.fields[f].removeEventListener('click', chesslib.board.codeSnippets.onClick,false);
						board.fields[f].classList.remove('chesshighlight');
					};
					if( promo ){
						board.promotionPopup.style.visibility = 'visible';
					} else {
						if (board.callThisAfterMove)
							setTimeout(board.callThisAfterMove.call(board), 0);
						delete board.move;
					}
				} else { //new field selected
					for (var f in board.fields) {
						if (!(board.fields.hasOwnProperty(f))) continue;
						board.fields[f].classList.remove('chesshighlight');
					};
					for (var p in board._possibleMoves[move]) {
						if (!(board._possibleMoves[move].hasOwnProperty(p))) continue;
						board.fields[board._possibleMoves[move][p]].removeEventListener('click', chesslib.board.codeSnippets.onClick,false);
					};
					board.move = {};
                    board_move = board.move;
					board_move[field] = board._possibleMoves[field];
					board.fields[field].classList.add('chesshighlight');
					for (var h in board_move[field]) {
						if(!(board_move[field].hasOwnProperty(h))) continue;
						board.fields[board_move[field][h]].classList.add('chesshighlight');
						board.fields[board_move[field][h]].addEventListener('click', chesslib.board.codeSnippets.onClick,false);
					};
				};
			};
		} else { //the user starts clicking
			board.move = {};
            board_move = board.move;
			board_move[field] = board._possibleMoves[field];
			board.fields[field].classList.add('chesshighlight');
			for (var h in board_move[field]) {
				if(!(board_move[field].hasOwnProperty(h))) continue;
				//the slice(0,2) is necessary for moves containing a "?"
				//indicating a promotion	
				board.fields[board_move[field][h].slice(0,2)].classList.add('chesshighlight');
				board.fields[board_move[field][h].slice(0,2)].addEventListener('click', chesslib.board.codeSnippets.onClick,false);
			};
		};
	};

	chesslib.board.codeSnippets.doThisAfterUserMovedOnBoardReferenceImp = function(pm){

	};

	chesslib.board.codeSnippets.setPossibleMoves = function(movesList, func){
		//a function that enables moves via mouse clicks.
		//the moveslist is an object with properties named like fields ("e4") marking the
		//start field of the move. The value is an array
		// with possible target fields of the figure placed on start field.
		// The board is stupid and has no clue of chess
		// hence you can specify a function invoked on the board
		// after the user moved in order to complete castling
		// or delete the pawn before the en passant field.
		// The promotion is handled by the function itself since it is key to describe
		// the complete move of the user.
		// a possible part of the movesList is 
		// {"e7":["e8?"]} Where the ? tells the board to ask the user which promotion
		// to perform
		this._possibleMoves = {};
		this.callThisAfterMove = func;
		for(var fromField in movesList) {
			if(!(movesList.hasOwnProperty(fromField))) continue;
			if(!(this.fields.hasOwnProperty(fromField))) continue;
			if(!(movesList[fromField] instanceof Array)) continue;
			this._possibleMoves[fromField] = movesList[fromField];
			this.fields[fromField].addEventListener('click', chesslib.board.codeSnippets.onClick,false);
		};

	};

	chesslib.board.codeSnippets.setFigures = function(pl) {
		if (typeof pl !== 'object') return;
		for (var f in pl) {
			if (!(pl.hasOwnProperty(f))) continue;
			if (!(this.fields.hasOwnProperty(f))) continue;
			if ('-kKqQbBnNrRpP'.indexOf(pl[f]) === -1) continue;
			if (pl[f] === '-') {
				var figureSrc = 'empty';
				delete this.fields[f].chess.figure;
			} else {
				var color = this.fields[f].classList.contains("whitefield")?"w":"b";
				var figureSrc = pl[f] + color + "Src";
				this.fields[f].chess.figure = pl[f];
			};
			this.fields[f].src = chesslib.board.images[figureSrc];
		};
	};

	chesslib.board.createBoardInElement = function (elem, blackTop){
//		deletes the content of elem and replaces it with a div that holds the chess 
//		board. This div has the following additional functions:
//		setFigures (o) where o is an object with the figures to be changed on the board
//		like {e4:k, f5:P, h1:-} which would place a black king on e4 a white pawn 
//		on f5 and clear the field h1 leaving the rest of the board untouched

		var nodeToInsert, i, j, imageNodeField, rank, white_field, boardNode;
		blackTop = blackTop || false;
		var letters	= blackTop ? ['a','b','c','d','e','f','g','h'] : ['h','g','f','e','d','c','b','a'];
		if (!elem instanceof HTMLElement) return false;
		elem.innerHTML = "";
		boardNode = document.createElement('div');
//		boardNode = object.Create(chesslib.board.prototypeBoardDiv);
		boardNode.id = elem.id + "_chessboard";
		boardNode.classList.add('chessboard');
		boardNode.chess = {};
		boardNode.chess.fields = {};  //the nodes that hold the images
		boardNode.chess.move = null;  //the move the user wants to do in the current position
		boardNode.chess._possibleMoves = null;  //the possible moves handed over and filtered; should be set by corresponding function
		boardNode.chess.setFigures = chesslib.board.codeSnippets.setFigures;
		boardNode.chess.setPossibleMoves = chesslib.board.codeSnippets.setPossibleMoves;
		chesslib.board.boards.push(boardNode);
		white_field = true;
		for (i=0; i<8; i++) {
			rank = blackTop ? 8 - i : i+1;
			nodeToInsert = document.createElement('div');
			nodeToInsert.id = boardNode.id + '_boardrank_' + rank;
			nodeToInsert.classList.add('chessboard_rank');
			for (j=0;j<8;j++){
				imageNodeField = chesslib.board.images.emptyImageTag.cloneNode();
				imageNodeField.style.width = "12.5%";
				imageNodeField.id = boardNode.id + "_field_" + letters[j] + rank;
				imageNodeField.classList.add(white_field ? 'whitefield' : 'blackfield');
				imageNodeField.classList.add('chessboard_field');
				imageNodeField.chess = {};
				boardNode.chess.fields[letters[j] + rank] = imageNodeField; 
				white_field = !white_field;
				nodeToInsert.appendChild(imageNodeField);
			};
			boardNode.appendChild(nodeToInsert);
			white_field = !white_field;
		};
		//promo popup declared here
		var promoNode = document.createElement('div');
		promoNode.id = boardNode.id + '_promoPopup';
		promoNode.classList.add("promotionOverlay");

		var divNode1 = document.createElement('div');
		var divNode2 = document.createElement('div');
		var divNode3 = document.createElement('div');

		promoNode.appendChild(divNode1);
		promoNode.appendChild(divNode2);
		promoNode.appendChild(divNode3);

		var funcOnClick = function(e){
			var short = this.parentNode.parentNode.parentNode.chess;
			short.move.promotion = 
				this.chess.promotion;
			this.parentNode.parentNode.style.visibility = 'hidden';
			if (short.callThisAfterMove)
				setTimeout(short.callThisAfterMove.call(short), 0);
			delete short.move;
		};

		var imgR = document.createElement('img');
		imgR.src = chesslib.board.images.RwSrc;
		imgR.chess= {};
		imgR.chess.promotion = 'R';
		imgR.onclick = funcOnClick;
		divNode2.appendChild(imgR);
		var imgN = document.createElement('img');
		imgN.src = chesslib.board.images.NwSrc;
		imgN.chess= {};
		imgN.chess.promotion = 'N';
		imgN.onclick = funcOnClick;
		divNode2.appendChild(imgN);
		var imgB = document.createElement('img');
		imgB.src = chesslib.board.images.BwSrc;
		imgB.chess= {};
		imgB.chess.promotion = 'B';
		imgB.onclick = funcOnClick;
		divNode2.appendChild(imgB);
		var imgQ = document.createElement('img');
		imgQ.src = chesslib.board.images.QwSrc;
		imgQ.chess= {};
		imgQ.chess.promotion = 'Q';
		imgQ.onclick = funcOnClick;
		divNode2.appendChild(imgQ);

		boardNode.appendChild(promoNode);
		boardNode.chess.promotionPopup = promoNode;
		elem.appendChild(boardNode);
		return boardNode;
	};
	return chesslib.board;
}) 